package com.cqgc.shiro;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.cqgc.pojo.entity.Result;
import com.cqgc.utils.ThreadLocalUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import com.cqgc.utils.JwtUtil;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;


public class JwtFilter extends AuthenticatingFilter {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Override
    protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String token = request.getHeader("Authorization");
        if (StringUtils.isEmpty(token)) {
            return  null;
        }
        Map<String, Object> map = JwtUtil.parseToken(token);
        ThreadLocalUtil.set(map);
        return new JWTToken(token);
    }
    //访问被拒绝
    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String token = request.getHeader("Authorization");
        if (StringUtils.isEmpty(token)) {
            //对跨域提供支持
            HttpServletResponse httpServletResponse = WebUtils.toHttp(servletResponse);
            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
            httpServletResponse.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            httpServletResponse.setCharacterEncoding("UTF-8");
            Result error = Result.error(403, "请先登录", null);
            String json = JSONUtil.toJsonStr(error);
            httpServletResponse.getWriter().print(json);
//            responseError(servletResponse, "请先登录");
            return false;
        }
        if (!JwtUtil.verify(token)){
            HttpServletResponse httpServletResponse = WebUtils.toHttp(servletResponse);
            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
            httpServletResponse.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            httpServletResponse.setCharacterEncoding("UTF-8");
            Result error = Result.error(403, "token错误", null);
            String json = JSONUtil.toJsonStr(error);
            httpServletResponse.getWriter().print(json);
            return false;
        }
        //token不为空
        return executeLogin(servletRequest, servletResponse);
    }


    /**
     * 跨域支持
     * @param request
     * @param response
     * @return
     * @throws Exception
     */

    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-control-Allow-Origin", res.getHeader("Origin"));
        res.setHeader("Access-control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
        res.setHeader("Access-Control-Allow-Headers", res.getHeader("Access-Control-Request-Headers"));
        if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
            res.setStatus(org.springframework.http.HttpStatus.OK.value());
            return false;
        }
        return super.preHandle(request, response);
    }
    /**
     * 将非法请求跳转到 /unauthorized/**
     */
    private void responseError(ServletResponse response, String message) {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 设置状态码为401或者你想要的任何错误码
        httpResponse.setContentType("application/json;charset=utf-8"); // 设置内容类型
        try {
            PrintWriter out = httpResponse.getWriter();
            // 创建一个错误信息的JSON字符串，这里示例使用了简单的字符串拼接，实际情况可以根据需要调整
            Result fail = Result.error(401, message, null);
            String errorJson = JSON.toJSONString(fail);
            out.println(errorJson);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 4.token失效时调用
     *
     * @param token
     * @param e
     * @param request
     * @param response
     * @return
     */
    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        HttpServletRequest httpRequest = WebUtils.toHttp(request);
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
        httpResponse.setContentType("application/json;charset=utf-8");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("Origin"));
        httpResponse.setCharacterEncoding("UTF-8");
        try {
            //处理登录失败的异常
            Throwable throwable = e.getCause() == null ? e : e.getCause();
            Result error = Result.error(403, "登录凭证已失效，请重新登录", null);
            String json = JSONUtil.toJsonStr(error);
            httpResponse.getWriter().print(json);
        } catch (IOException e1) {
        }
        return false;
    }
}